/*
 * @features: 功能
 * @description: 说明
 * @Date: 2021-09-13 23:55:11
 * @Author: judu233(769471424@qq.com)
 * @LastEditTime: 2022-08-27 23:51:05
 * @LastEditors: judu233
 */

import { ExtendsLoad } from "../CCExtends";


/**扩展原型组件 */
@ExtendsLoad(cc.Sprite)
export class SpriteBaseExtends {
    /**
    * 将 Base64 字符转为 cc.Texture2D 资源
    * @param base64 Base64 字符
    */
    static base64ToTexture(base64: string): cc.Texture2D {
        const image = document.createElement('img');
        image.src = base64;
        const texture = new cc.Texture2D();
        texture.initWithElement(image);
        image.remove();
        return texture;
    }

    /**
    * 将 Base64 字符转为二进制数据
    * @param base64 Base64 字符
    */
    static base64ToBlob(base64: string): Blob {
        const strings = base64.split(',');
        const type = /image\/\w+|;/.exec(strings[0])[0];
        const data = window.atob(strings[1]);
        const arrayBuffer = new ArrayBuffer(data.length);
        const uint8Array = new Uint8Array(arrayBuffer);
        for (let i = 0; i < data.length; i++) {
            uint8Array[i] = data.charCodeAt(i) & 0xff;
        }
        return new Blob([uint8Array], { type: type });
    }

    /**
     * 创建一个纯色的图片
     * @returns sf
     */
    static createSplashSprite() {
        let texture = new cc.RenderTexture();
        texture.initWithData(new Uint8Array([0, 255, 255]), cc.Texture2D.PixelFormat.RGB888, 1000, 1000);
        texture.packable = false;
        let sf = new cc.SpriteFrame(texture);
        sf.addRef();
        window['sf'] = sf;
        console.log(sf);
        return sf;
    }
}
/**扩展组件实例方法 */
@ExtendsLoad(cc.Sprite.prototype)
export class SpriteExtends {
    /**
     * @description 从网络加载图片，推荐使用第二种方式
     * @param url 网络地址，如 : http://tools.itharbors.com/res/logo.png
     * @param completeCallback 加载完成回调
     * @param defaultSpriteFrame 加载图片失败后，使用的默认图片,当传入string时，会动态加载该默认图片
     * @param isNeedCache 是否需要缓存到本地,如果不需要，每次都会从网络拉取资源,默认都会缓存到本地
     * @param config.retain 远程加载的资源是否驻留在内存中,默认都不驻留内存
     * @example
     * 示例1：
     * let sprite = imageNode.getComponent(cc.Sprite);
     * sprite.loadRemoteImage({url :"http://tools.itharbors.com/res/logo.png", defaultSpriteFrame : HALL("textures/avatar_default_0.png"), view : this,completeCallback : (data)=>{
     * 		if ( data ) { do something }
     * }});
     * 
     * 示例2:
     * let sprite = imageNode.getComponent(cc.Sprite);
     * sprite.loadRemoteImage({url :"http://tools.itharbors.com/res/logo.png", defaultSpriteFrame : HALL("textures/avatar_default_0.png"), view : this});
     * 
     * 示例3：
     * let sprite = imageNode.getComponent(cc.Sprite);
     * sprite.loadRemoteImage({url :"http://tools.itharbors.com/res/logo.png", view : this});
     * }
     */
    static loadRemoteImage = function (config: any) {
        let me = this;
        if (config.isNeedCache == undefined || config.isNeedCache == null) {
            config.isNeedCache = true;
        }
        let isRetain = false;
        if (config.retain) {
            isRetain = true;
        }
        // let defaultBundle = getBundle({ bundle: config.defaultBundle, view: config.view });
        // Manager.assetManager.remote.loadImage(config.url, config.isNeedCache).then((data) => {
        //     if (data) {
        //         setSpriteSpriteFrame(config.view, config.url, me, data, config.completeCallback, Macro.BUNDLE_REMOTE, Resource.Type.Remote, isRetain);
        //     } else {
        //         if (config.defaultSpriteFrame) {
        //             if (typeof config.defaultSpriteFrame == "string") {
        //                 //动态加载了一张图片，把资源通知管理器
        //                 Manager.cacheManager.getCacheByAsync(config.defaultSpriteFrame, SpriteFrame, defaultBundle).then((spriteFrame) => {
        //                     setSpriteSpriteFrame(config.view, config.defaultSpriteFrame, me, spriteFrame, config.completeCallback, defaultBundle);
        //                 });
        //             }
        //         }
        //         if (config.completeCallback && isValid(me)) config.completeCallback(data);
        //     }
        // });
    };

    /**
     * @description 加载本地图片
     * @param url 图片路径 {urls:string[],key:string} urls 为纹理名如果有此纹理会打包成多张，此时需要传入所有纹理的地址，key指纹理中名字
     * @param view 所属视图，UIView的子类
     * @param completeCallback 完成回调
     * @example
     * 示例1：
     * sprite.getComponent(cc.Sprite).loadImage({url:{urls:["plist/fish_30","plist/fish_30_1","plist/fish_30_2"],key:"fishMove_030_28"},view:this});
     * 示例2：
     * sprite.getComponent(cc.Sprite).loadImage({url:"hall/a",view:this});
     */
    //loadImage( config : { url : string | {urls:string[],key:string} , view : any , completeCallback?:(data : SpriteFrame)=>void});
    static loadImage(config: any) {
        let me = this;
        let view = config.view;
        let url = config.url;
        let completeCallback = config.completeCallback;
        // let bundle = getBundle(config);
        // if (typeof url == "string") {
        //     Manager.cacheManager.getCacheByAsync(url, SpriteFrame, bundle).then((spriteFrame) => {
        //         setSpriteSpriteFrame(view, url, me, spriteFrame, completeCallback, bundle);
        //     });
        // } else {
        //     //在纹理图集中查找
        //     Manager.cacheManager.getSpriteFrameByAsync(url.urls, url.key, view, addExtraLoadResource, bundle).then((data) => {
        //         if (data && data.isTryReload) {
        //             //来到这里面程序已经崩溃了，无意义在处理了
        //         } else {
        //             setSpriteSpriteFrame(view, data.url, me, data.spriteFrame as SpriteFrame, completeCallback, bundle, Resource.Type.Local, false, true);
        //         }
        //     });
        // }
    }

    /**
     * 获取纹理中指定像素的颜色，原点为左上角，从像素 (1, 1) 开始。
     * @param texture 纹理
     * @param x x 坐标
     * @param y y 坐标
     * @example
     * // 获取纹理左上角第一个像素的颜色
     * const color = ImageUtil.getPixelColor(texture, 1, 1);
     * // cc.color(50, 100, 123, 255);
     */
    static getPixelColor(x: number, y: number) {
        let texture = (this as any as cc.Sprite).spriteFrame?.getTexture();
        if (!texture) {
            return;
        }
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        canvas.width = texture.width;
        canvas.height = texture.height;
        const image = texture['image'].data as CanvasImageSource;
        ctx.drawImage(image, 0, 0, texture.width, texture.height);
        const imageData = ctx.getImageData(0, 0, texture.width, texture.height);
        const pixelIndex = ((y - 1) * texture.width * 4) + (x - 1) * 4;
        const pixelData = imageData.data.slice(pixelIndex, pixelIndex + 4);
        const c = new cc.Color(pixelData[0], pixelData[1], pixelData[2], pixelData[3]);
        // image.remove();
        canvas.remove();
        return c;
    }

    /**
    * 将图像转为 Base64 字符（仅 png、jpg 或 jpeg 格式资源）
    * @param url 图像地址
    * @param callback 完成回调
    */
    static imageToBase64(url: string, callback?: (dataURL: string) => void) {
        return new Promise(res => {
            let extname = /\.png|\.jpg|\.jpeg/.exec(url)?.[0];
            if (['.png', '.jpg', '.jpeg'].includes(extname)) {
                const canvas = document.createElement('canvas');
                const ctx = canvas.getContext('2d');
                const image = new Image();
                image.src = url;
                image.onload = () => {
                    canvas.height = image.height;
                    canvas.width = image.width;
                    ctx.drawImage(image, 0, 0);
                    extname = extname === '.jpg' ? 'jpeg' : extname.replace('.', '');
                    const dataURL = canvas.toDataURL(`image/${extname}`);
                    callback && callback(dataURL);
                    res(dataURL);
                    image.remove();
                    canvas.remove();
                }
            } else {
                console.warn('Not a jpg/jpeg or png resource!');
                callback && callback(null);
                res(null);
            }
        });
    }

    /**
     * 更新图片
     * @param url 要更新加载的图片地址
     */
    static setSf(url: string) {
        let sp = this as any as cc.Sprite;
        cc.resources.load<cc.SpriteFrame>(url, cc.SpriteFrame, (err, spriteFrame) => {
            if (err) {
                console.error(' not find url :' + url);
                return;
            }
            if (cc.isValid(sp) && cc.isValid(sp.node)) {
                sp.spriteFrame = spriteFrame;
            }
        })
    }

    /**
     * 根据图集名称来设精灵图片
     * @param atilsPath 图集名称
     * @param pngStr 图片名称
     */
    static setSfByAtlas(atilsPath: string, pngStr: string) {
        let sp = this as any as cc.Sprite;
        cc.resources.load<cc.SpriteAtlas>(atilsPath, cc.SpriteAtlas, (err, atlas) => {
            if (err) {
                console.error(err);
                return;
            }
            if (!cc.isValid(sp)) {
                return;
            }
            let temp = atlas.getSpriteFrame(pngStr);
            if (temp != null) {
                sp.spriteFrame = temp;
            } else {
                cc.error(`${pngStr}->读取图片为空: ${atilsPath}`);
            }
        });
    }


    /**置灰图片*/
    static setSpMtGray() {
        let grayMt = cc.Material.getBuiltinMaterial("2d-gray-sprite");
        let sp = this as any as cc.Sprite;
        sp.setMaterial(0, grayMt);
    }

    /**设置图片普通材质 */
    static setSpMtNormal() {
        let normalMt = cc.Material.getBuiltinMaterial('2d-sprite');
        let sp = this as any as cc.Sprite;
        sp.setMaterial(0, normalMt);
    }

    /**设置组件为纯色贴图 */
    static setSplashSprite() {
        let sp = this as any as cc.Sprite;
        sp.spriteFrame = cc.Sprite.createSplashSprite();
    }

    /**
     * 根据指定尺寸切当前的图片
     * @param size 要切的图片rext
     */
    static cropSf(size: cc.Rect) {
        let sp = this as any as cc.Sprite;
        let sf = sp.spriteFrame;
        if (sf) {
            sp.spriteFrame = null;
            sf.setRect(size);
            sp.spriteFrame = sf;
        } else {
            console.warn('当前sp组件没有图片，无法切图');
        }
    }


}
